var Utils = {};
var timeSec = 0;
// 操作间隔时间
Utils.runInterval = 1000;
// 操作超时时间
Utils.overTime = 5000;
// 运行间隔时间 分钟:秒钟
Utils.runTimeStr = '00:00';
// 正在运行的子线程
Utils.runThread = null;
// 悬浮顶部信息
Utils.topTips = null;
// 每秒执行任务
Utils.secondTimerTask = null;

// 单toast提示
var _toast_ = toast;
toast = function (message) {
    _toast_(message);
    if (threads.currentThread() == Utils.runThread) {
        sleep(2000);
    }
}

/**
 * 显示运行日志信息
 * @param {string} message 消息内容
 * @param {boolean} writeLog 写入日志
 */
Utils.showLogInfo = function (message, writeLog) {
    ui.run(() => {
        // toast(message);
        Utils.setTopTipsText(message);
        if (writeLog) {
            console.log(Utils.runTimeStr + ' => ' + message);
        }
    });
}

/**
 * 获取状态栏高度
 */
Utils.getStatusBarHeight = function () {
    let resources = context.getResources();
    let resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
    let height = resources.getDimensionPixelSize(resourceId);
    return height;
}

/**
 * 退出应用
 * @param {string} toast 自定义显示Toast信息
 */
Utils.exitApp = function (run, toast) {
    try {
        if (run != null) run();
        Utils.stopKeepAliveService();
        Utils.showLogInfo(toast != null ? toast : '停止退出脚本运行!', true);
        Utils.expandConsoleWindow(true);
        if (Utils.topTips != null) {
            Utils.topTips.close();
        }
        if (Utils.runThread != null) {
            Utils.runThread.interrupt();
            Utils.runThread = null;
        }
        exit();
    } catch (error) {
        Utils.showLogInfo('退出脚本运行失败:' + error, true);
    }
}

/**
 * 等待指定文本控件出现
 * @param {string | UiSelector} target 目标文本或控件
 * @param {{string, UiObject?}} callback 结果返回
 * @param {boolean} findDesc 查找描述文本
 * @param {string} showText 指定显示文本
 * @param {number} waitRunTime 等待运行延迟
 */
Utils.waitFindText = function (target, callback, findDesc, showText, waitRunTime) {
    let textStr = '';
    if (showText != null) {
        textStr = showText;
    } else {
        if (typeof target == 'string') {
            textStr = target;
        }
    }
    Utils.waitRunInterval('开始查找<' + textStr + '>控件', waitRunTime);
    let isCallback = false;
    let startFindTime = Date.now();
    while (!isCallback) {
        let widget = null;
        if (typeof target == 'string') {
            widget = text(target).findOnce();
            if (widget == null && findDesc) {
                widget = desc(target).findOnce();
            }
        } else {
            widget = target;
        }
        if (widget != null) {
            isCallback = true;
            Utils.showLogInfo('<' + textStr + '>控件查找成功');
            callback(textStr, widget);
            break;
        } else if (Date.now() - startFindTime >= Utils.overTime) {
            isCallback = true;
            Utils.showLogInfo('查找不到<' + textStr + '>控件，超时失败', true);
            callback(textStr, null);
            break;
        }
    }
}

/**
 * 查找等待点击文本控件
 * @param {string | UiSelector} target 目标文本或控件
 * @param {boolean} callback 结果返回
 * @param {boolean} findDesc 查找描述文本
 * @param {string} showText 指定显示文本
 * @param {number} waitRunTime 等待运行延迟
 */
Utils.findClickText = function (target, callback, findDesc, showText, waitRunTime) {
    Utils.waitFindText(target, (textStr, widget) => {
        Utils.clickTargetWidget(widget, callback, textStr);
    }, findDesc, showText, waitRunTime);
}

/**
 * 点击目标控件
 * @param {UiObject} widget 目标控件
 * @param {boolean} callback 结果返回
 * @param {string} showText 指定显示文本
 */
Utils.clickTargetWidget = function (widget, callback, showText) {
    let textStr = '';
    if (showText != null) {
        textStr = showText;
    } else {
        if (widget.text() != null) {
            textStr = widget.text();
        } else if (widget.desc() != null) {
            textStr = widget.desc();
        }
    }
    if (widget != null) {
        if (click(widget.bounds().centerX(), widget.bounds().centerY())) {
            Utils.showLogInfo('<' + textStr + '>控件点击成功');
            callback(true);
        } else {
            Utils.showLogInfo('<' + textStr + '>控件点击失败', true);
            callback(false);
        }
    } else {
        Utils.showLogInfo('控件点击失败', true);
        callback(false);
    }
}

/**
 * 等待执行间隔时间
 * @param {string} text 提示显示文本
 * @param {number} waitRunTime 等待运行延迟
 * @param {boolean} writeLog 写入日志
 */
Utils.waitRunInterval = function (text, waitRunTime, writeLog) {
    let sleepTime = waitRunTime != null ? waitRunTime : Utils.runInterval;
    if (sleepTime > 0) {
        Utils.showLogInfo('延迟' + parseFloat((sleepTime / 1000.0).toFixed(1)) + '秒 ' + (text != null ? text : ''), writeLog);
    } else {
        Utils.showLogInfo('不延迟 ' + (text != null ? text : ''), writeLog);
    }
    sleep(sleepTime);
}

/**
 * 开启运行线程
 */
Utils.startRunThread = function (run) {
    if (auto.service == null) {
        Utils.showLogInfo("请开启无障碍服务!");
    } else if (!floaty.checkPermission()) {
        Utils.showLogInfo("请开启悬浮窗权限!");
    } else {
        // 开启定时器保持悬浮窗不被关闭且更新执行时间
        setInterval(() => {
            // 设置顶部显示执行时间
            timeSec += 1;
            let min = parseInt(timeSec / 60);
            let sec = parseInt(timeSec % 60);
            let minText = min == 0 ? '00' : (min < 10 ? '0' + min : min);
            let secText = sec == 0 ? '00' : (sec < 10 ? '0' + sec : sec);
            Utils.runTimeStr = minText + ":" + secText;
            if (Utils.topTips != null) {
                ui.run(() => {
                    Utils.topTips.time.setText(Utils.runTimeStr);
                });
            }
            if (Utils.secondTimerTask != null) {
                Utils.secondTimerTask();
            }
        }, 1000);
        // 屏蔽音量键调节声音
        events.setKeyInterceptionEnabled("volume_up", true);
        // 启用按键监听
        events.observeKey();
        // 监听音量键按下
        events.onKeyDown("volume_up", () => {
            Utils.exitApp();
        });
        Utils.runThread = threads.start(run);
    }
}
// ------------------------------通用工具------------------------------- //

// ------------------------------控制台及服务------------------------------- //
/**
 * 开启控制台显示
 */
Utils.startShowConsole = function () {
    threads.start(() => {
        console.show();
        console.setTitle("日志记录");
        console.setCanInput(false);
        // 需要延迟修改窗体
        sleep(100);
        console.setSize(device.width - 20, device.height / 3);
        console.setPosition(0, Math.max(Utils.getStatusBarHeight(), 100));
        // 控制台最小化
        Utils.expandConsoleWindow(false);
    });
}
/**
 * 获取控制台窗口对象
 */
Utils.getConsoleWindow = function () {
    let mConsole = runtime.console;
    let field = mConsole.class.getDeclaredField("mConsoleFloaty");
    field.setAccessible(true);
    let mConsoleFloaty = field.get(mConsole);
    let mConsoleView = mConsoleFloaty.getExpandedView();
    return mConsoleView;
}
/**
 * 展开控制台窗口
 * @param {boolean} expand 
 */
Utils.expandConsoleWindow = function (expand) {
    let mConsole = runtime.console;
    let field = mConsole.class.getDeclaredField("mFloatyWindow");
    if (field != null) {
        field.setAccessible(true);
        let mFloatyWindow = field.get(mConsole);
        ui.run(() => {
            if (expand) {
                mFloatyWindow.expand();
            } else {
                mFloatyWindow.collapse();
            }
        });
    }
}

/**
 * 开启前台服务保活
 * @param {string} idStr 
 * @param {string} nameStr 
 */
Utils.startKeepAliveService = function (nameStr, idStr) {
    try {
        idStr = idStr || "";
        let channelId = idStr + ".foreground";
        let channelName = nameStr + "前台运行服务";
        let contentTitle = nameStr + "正在运行中";
        let contentText = "请勿手动移除该通知";
        let ticker = nameStr + "已启动";
        let manager = context.getSystemService(android.app.Service.NOTIFICATION_SERVICE);
        let notification;
        if (device.sdkInt >= 26) {
            let channel = new android.app.NotificationChannel(channelId, channelName, android.app.NotificationManager.IMPORTANCE_DEFAULT);
            channel.enableLights(true);
            channel.setLightColor(0xff0000);
            channel.setShowBadge(false);
            manager.createNotificationChannel(channel);
            notification = new android.app.Notification.Builder(context, channelId).setContentTitle(contentTitle)
                .setContentText(contentText).setWhen(new Date().getTime()).setTicker(ticker)
                .setOngoing(true).setSmallIcon(-1).build();
        } else {
            notification = new android.app.Notification.Builder(context).setContentTitle(contentTitle)
                .setContentText(contentText).setWhen(new Date().getTime()).setTicker(ticker)
                .setSmallIcon(-1).build();
        }
        manager.notify(1, notification);
    } catch (error) {
        Utils.showLogInfo("前台保活服务启动失败:" + error, true);
    }
}

/**
 * 停止前台服务保活
 */
Utils.stopKeepAliveService = function () {
    let manager = context.getSystemService(android.app.Service.NOTIFICATION_SERVICE);
    manager.cancelAll();
}
// ------------------------------控制台及服务------------------------------- //

// ------------------------------悬浮顶部信息------------------------------- //
Utils.showTopTips = function () {
    Utils.topTips = floaty.rawWindow(
        <frame w="*" bg="#cdcdcd" >
            <vertical w="*" gravity="center">
                <text id="time" w="auto" textColor="red" textStyle="bold" textSize="10sp">00:00</text>
                <text id="text" w="auto" textColor="red" textStyle="bold">按音量+号键可退出脚本!</text>
            </vertical>
        </frame>
    );
    Utils.topTips.setTouchable(false);
    Utils.topTips.setPosition(0, 0);
    // Utils.topTips.setPosition(0, -Math.max(Utils.getStatusBarHeight(), 100));
    Utils.topTips.setSize(-1, Math.max(Utils.getStatusBarHeight(), 100));
};

/**
 * 设置顶部提示信息
 * @param {string} text 信息内容
 */
Utils.setTopTipsText = function (text) {
    if (Utils.topTips != null) {
        Utils.topTips.text.setText(text);
    }
};
// ------------------------------悬浮顶部信息------------------------------- //

module.exports = Utils;